package com.utils;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 * 加密工具类，提供常见的加密和解密方法。
 * <p>
 * 支持的加密方式包括：
 * <ul>
 *     <li>MD5</li>
 *     <li>SHA-256</li>
 *     <li>BCrypt</li>
 *     <li>Base64</li>
 * </ul>
 */
public class EncryptionUtils {


    private static final BCryptPasswordEncoder bcryptEncoder = new BCryptPasswordEncoder();
    // 对字符串进行 MD5 加密

    /**
     * 计算字符串的MD5哈希值
     *
     * @param input 要计算哈希值的字符串
     * @return 计算出的MD5哈希值
     */
    public static String md5(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] hash = md.digest(input.getBytes(StandardCharsets.UTF_8));

            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) hexString.append('0');
                hexString.append(hex);
            }

            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("MD5 algorithm not found", e);
        }
    }

    /**
     * 使用 MD5 加密字符串。
     *
     * @param input 要加密的字符串
     * @return 加密后的 MD5 哈希值
     */
    public static String encryptMD5(String input) {
        return hash(input, "MD5");
    }

    /**
     * 使用 SHA-256 加密字符串。
     *
     * @param input 要加密的字符串
     * @return 加密后的 SHA-256 哈希值
     */
    public static String encryptSHA256(String input) {
        return hash(input, "SHA-256");
    }

    /**
     * 使用 BCrypt 加密密码。
     *
     * @param password 要加密的密码
     * @return 加密后的 BCrypt 哈希值
     */
    public static String encryptBCrypt(String password) {
        return bcryptEncoder.encode(password);
    }

    /**
     * 验证原始密码与加密后的 BCrypt 密码是否匹配。
     *
     * @param rawPassword     原始密码
     * @param encodedPassword 加密后的 BCrypt 密码
     * @return 如果匹配返回 true，否则返回 false
     */
    public static boolean verifyBCrypt(String rawPassword, String encodedPassword) {
        return bcryptEncoder.matches(rawPassword, encodedPassword);
    }

    /**
     * 使用 Base64 编码字符串。
     *
     * @param input 要编码的字符串
     * @return 编码后的 Base64 字符串
     */
    public static String encryptBase64(String input) {
        return Base64.getEncoder().encodeToString(input.getBytes());
    }

    /**
     * 解码 Base64 编码的字符串。
     *
     * @param encodedInput 编码后的 Base64 字符串
     * @return 解码后的字符串
     */
    public static String decryptBase64(String encodedInput) {
        return new String(Base64.getDecoder().decode(encodedInput));
    }

    /**
     * 使用指定算法生成字符串的哈希值。
     *
     * @param input     要生成哈希值的字符串
     * @param algorithm 哈希算法（如 "MD5", "SHA-256"）
     * @return 哈希值
     */
    private static String hash(String input, String algorithm) {
        try {
            MessageDigest md = MessageDigest.getInstance(algorithm);
            byte[] digest = md.digest(input.getBytes());
            StringBuilder sb = new StringBuilder();
            for (byte b : digest) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("没有此算法: " + algorithm, e);
        }

    }
}
